﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PES_TurnierManager.Model
{
    public delegate void ModelNewGroup(string groupName);
    public delegate void ModelPlayerAddedToGroup(string groupName, HumanPlayer player);
    public delegate void ModelMatchesSet(List<Match> matches, string groupName);
    public delegate void ModelMatchPlayed(Match match);
    public delegate void ModelGroupUpdate(Group group);
    public delegate void ModelPlayerRemovedFromGroup(string playerName, string groupName);

    /// <summary>
    /// The Main Class holding the whole data of the Tournament
    /// </summary>
    public class Model
    {
        private Tournament mTournament;

        //Notify that a new group was created
        public event ModelNewGroup NewGroup; 

        //Notify that a player was added to a group
        public event ModelPlayerAddedToGroup PlayerAddedToGroup;

        //Notify that the matches have been generated for a group
        public event ModelMatchesSet MatchesSet;

        //Notify that the result of a match has been enterd
        public event ModelMatchPlayed MatchPlayed;

        public event ModelGroupUpdate GroupUpdate;

        public event ModelPlayerRemovedFromGroup PlayerRemovedFromGroup;

        public Model()
        {
            mTournament = new Tournament();
        }

        /// <summary>
        /// adds a group to the tournament
        /// </summary>
        /// <param name="name">name of the group</param>
        public bool addGroup(string name, bool with2Legs)
        {
            mTournament.addGroup(name, with2Legs);
            fireNewGroupEvent(name);
            return true;
        }

        /// <summary>
        /// gets the group.
        /// </summary>
        /// <param name="groupName">name of the group</param>
        /// <returns>null if the group doesnt exist</returns>
        public Group getGroup(string groupName)
        {
            return mTournament.getGroup(groupName);
        }

        /// <summary>
        /// Checks if a group with the passed name already exists
        /// </summary>
        /// <param name="name">name of the group</param>
        /// <returns>True if the group exists. False otherwise</returns>
        public bool existGroup(string name)
        {
            if(getGroup(name) != null)
                return true; //Group already exists

            return false; //Group doesnt exist
        }

        /// <summary>
        /// Adds a player to a Group
        /// </summary>
        /// <param name="groupName">name of the group</param>
        /// <param name="playerName">name of the player</param>
        /// <param name="teamName">name of the players Team</param>
        public void addPlayerToGroup(string groupName, string playerName, string teamName)
        {
            HumanPlayer newPlayer = getGroup(groupName).addHumanPlayer(playerName, teamName);
            if (PlayerAddedToGroup != null)
                PlayerAddedToGroup(groupName, newPlayer);
        }

        /// <summary>
        /// fires the "NewGroup" Event
        /// </summary>
        /// <param name="groupName">name of the new group</param>
        private void fireNewGroupEvent(string groupName)
        {
            if(NewGroup != null)
                NewGroup(groupName);
        }

        /// <summary>
        /// Ganarates the matches for a group
        /// </summary>
        /// <param name="group">the group which the matches should be generated for</param>
        public void generateMatchesForGroup(string group)
        {
            List<Match> matches = mTournament.generateMatchesForGroup(group);

            //Fire Event that the matches have been generated for a group
            if (MatchesSet != null)
                MatchesSet(matches, group);
        }

        /// <summary>
        /// Adds the result to a match
        /// </summary>
        /// <param name="groupName">name of the group</param>
        /// <param name="matchID">the matchID</param>
        /// <param name="homeScore">score of the home team</param>
        /// <param name="guestScore">score of the guest team</param>
        public void addResultForMatch(string groupName, uint matchID, uint homeScore, uint guestScore)
        {
            getGroup(groupName).addMatchResult(matchID, homeScore, guestScore);

            //Fire Event that a group was updated
            if (GroupUpdate != null)
                GroupUpdate(getGroup(groupName));
        }

        /// <summary>
        /// Checks if a group has started yet. 
        /// (A group is markes as started when the first game result
        ///  is enterd)
        /// </summary>
        /// <param name="groupName">name of the group</param>
        /// <returns>true if the group has been started</returns>
        public bool hasGroupStarted(string groupName)
        {
            return getGroup(groupName).hasGroupStarted();
        }

        /// <summary>
        /// Removes a player from a group
        /// </summary>
        /// <param name="plyaerName">player to remove</param>
        /// <param name="groupName">name of the player´s group</param>
        /// <returns>true if the player could be removed from the group</returns>
        public bool removePlayerFromGroup(string plyaerName, string groupName)
        {
            if (!existGroup(groupName) || !getGroup(groupName).existPlayer(plyaerName))
            {
                return false;
            }
            getGroup(groupName).removePlayer(plyaerName);

            if (PlayerRemovedFromGroup != null)
                PlayerRemovedFromGroup(plyaerName, groupName);
            return true;
        }
    }
}
